import os
from datetime import datetime
from typing import List

from fastapi import UploadFile, File
from loguru import logger
from sqlalchemy.orm import Session

from apis_module.dao.liker_dao import LikerDao
from apis_module.dao.reviews_dao import ReviewsDao
from apis_module.jsonvo.reviews_vo import ReviewsListQueryModel, UploadReviewsImageModel, ReviewsViewModel, \
    ReviewsFormModel, ReviewsImagesRequest, ReviewsLikerRequest
from apis_module.model.reviews_model import ReviewsModel
from config.env import PictureServiceConfig
from utils.picture_util import PictureUtil
from utils.common_util import get_server_image_storage_path_by_os


class ReviewsService:
    """
    点评逻辑处理服务
    """

    @classmethod
    def get_reviews_list_service(cls, result_db: Session, query_model: ReviewsListQueryModel, is_all: bool):
        """
        获得点评列表
        :param result_db: orm对象
        :param query_model: 查询参数模型
        :param is_all: 是否要全部结果，true：不分页, false：分页结果
        :return:
        """
        if not is_all:
            review_list = ReviewsDao.get_reviews_list(result_db, query_model)

        else:
            review_list = ReviewsDao.get_reviews_list_no_paginated(result_db, query_model)

        return review_list

    @classmethod
    def get_reviews_details(cls, result_db: Session, user_id: str, query_id: str):
        """
        获得点评详情服务
        :param result_db:
        :param query_id:
        :return:
        """
        result = ReviewsDao.get_reviews_by_id(result_db, query_id)
        liker_obj = LikerDao.get_liker_by_composite_id(result_db, user_id, query_id)
        result.reviews_id = str(result.reviews_id)
        result.create_time = result.create_time.strftime('%Y-%m-%d %H:%M:%S')
        result.release_time = result.release_time.strftime('%Y-%m-%d')
        result.last_modify_time = result.last_modify_time.strftime('%Y-%m-%d %H:%M:%S')
        if liker_obj is None:
            result.liked = False
        else:
            result.liked = True

        return result

    @classmethod
    def upload_file_save(cls, file: UploadFile = File(...), r_id: str = ''):
        """
        测试图片存储
        :param file:
        :type r_id: object
        """
        try:
            save_as_name = PictureUtil.save_upload_picture(r_id, file)
            return save_as_name
        except Exception as e:
            print(e)
            logger.error(e)

    @classmethod
    def create_reviews_service(cls, result_db: Session, reviews_model: ReviewsFormModel):
        """
        创建点评服务。
        通过is_release字段来判断，是发布还是保存草稿箱，会有不同的处理。
        :param result_db:
        :param reviews_model:
        :return: 生成的ReviewID
        """
        new_model: ReviewsModel = ReviewsModel()
        new_model.reviews_title = reviews_model.reviews_title
        new_model.reviews_content = reviews_model.reviews_content
        new_model.reviews_author = reviews_model.reviews_author
        new_model.reviews_avatar = reviews_model.reviews_avatar
        new_model.user_id = reviews_model.user_id
        new_model.reviews_group_code = reviews_model.reviews_group_code
        new_model.group_chain = reviews_model.group_chain
        new_model.liker_num = reviews_model.liker_num
        new_model.is_release = reviews_model.is_release

        if reviews_model.is_release:
            new_model.release_time = datetime.now()
        new_model.create_time = datetime.now()
        new_model.last_modify_time = datetime.now()

        result = ReviewsDao.create_reviews(result_db, new_model)

        return result

    @classmethod
    def update_reviews_images_service(cls, result_db: Session, images_model: ReviewsImagesRequest) -> bool:
        """
        根据图片对象生成URL和主图的展示图，保存数据库
        :param result_db:
        :param images_model:
        :return: True成功
        """
        try:
            model = ReviewsModel()
            http_url = PictureServiceConfig.SERVER_PATH + '/' + images_model.reviews_id + '/'
            dir_name = '/' + images_model.reviews_id + '/'
            local_url = get_server_image_storage_path_by_os() + dir_name
            filename = os.path.abspath(local_url + images_model.primary_image)
            primary_image_name = PictureUtil.gen_thumbnails(filename, size=(194, 194))
            primary_image_url = http_url + os.path.basename(primary_image_name)

            names = []
            # 文件名转URL
            for img_name in images_model.reviews_images:
                names.append(http_url + img_name)
            model.reviews_id = images_model.reviews_id
            model.primary_image = primary_image_url
            model.reviews_images = names
            model.is_release = images_model.is_release

            result = ReviewsDao.update_reviews_by_images(result_db, model)

            return result
        except Exception as e:
            logger.error(e)
            return False

    @classmethod
    def update_reviews_service(cls, result_db: Session, reviews_model: ReviewsViewModel):
        pass

    @classmethod
    def save_reviews_pictures(cls, result_db: Session, form_data: UploadReviewsImageModel):
        """
        创建一个简单的点评必选项实体，压缩照片，存储照片，生成照片的URL，写数据库，返回文件URL[]
        :param form_data:
        :param result_db:
        :return: 保存后的文件URL[]
        """
        model = ReviewsViewModel()
        model.reviews_title = 'New Reviews In Template Path'
        model.reviews_group_code = 0
        model.reviews_author = form_data.reviews_author
        model.reviews_avatar = form_data.reviews_avatar
        model.user_id = form_data.user_id

        reviews: ReviewsModel = ReviewsDao.create_reviews(result_db, model)
        files: List[UploadFile] = form_data.files
        saved_files: List[str] = PictureUtil.save_upload_picture('/'.join(reviews.reviews_id), files)
        http_files: List[str] = []
        local_files: list[str] = []
        if len(saved_files) > 0:
            _server_path = PictureServiceConfig.SERVER_PATH
            _local_path = get_server_image_storage_path_by_os()
            for f in saved_files:
                http_files.append(_server_path.join(['/', reviews.reviews_id, '/', f]))
                local_files.append(os.path.abspath(_local_path.join(['/', reviews.reviews_id, '/', f])))

            # 生成缩略图, 前端展示的是340rpx * 340rpx
            PictureUtil.gen_thumbnails(local_files, size=(170, 170))
            reviews.reviews_images = saved_files
            try:
                ReviewsDao.update_reviews_by_images(result_db, reviews)
                result_db.commit()
                result = dict(is_success=True, message='更新成功')
            except Exception as e:
                result_db.rollback()
                result = dict(is_success=False, message=str(e))
        else:
            result_db.rollback()
            result = dict(is_success=False, message='图片保存未成功')

    @classmethod
    def update_reviews_liker_service(cls, result_db: Session, request_data: ReviewsLikerRequest):
        try:
            ReviewsDao.update_reviews_liker(result_db, request_data.reviews_id, request_data.liker_num)
            # TODO(me): 这里要添加关联表的插入
            if request_data.method == 'plus':
                LikerDao.add_liker(result_db, request_data.user_id, request_data.reviews_id)
            else:
                LikerDao.del_liker(result_db, request_data.user_id, request_data.reviews_id)
        except Exception as e:
            raise e

    @classmethod
    def get_liked_by_user_service(cls, result_db: Session, user_id: int):
        try:
            result_list = LikerDao.get_liker_list_by_uid(result_db, user_id)
            results: list[str] = []
            for row in result_list:
                results.append(str(row.reviews_id))
            return results
        except Exception as e:
            raise e


    @classmethod
    def add_reviews_look_service(cls, result_db: Session, reviews_id: str):
        result = ReviewsDao.add_look(result_db, reviews_id)
        return result
